<template>
    <Dialog v-model="show" :title="title" width="1200px" append-to-body>
        <el-form ref="formRef" label-width="120px" :model="form" :rules="rules" :disabled="title=='查看'"  style="margin-right: 10px">
            <el-row>
                <el-col :span="12">
                    <el-form-item label="名称" prop="syncTaskName">
                        <el-input v-model="form.syncTaskName" placeholder="请输入名称" clearable/>
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="类型" prop="syncTaskType">
                        <el-select v-model="form.syncTaskType" @change="selectSyncTaskType" placeholder="请选择类型"
                                   clearable>
<!--                            <el-option label="DBToDB" value="1"/>-->
<!--                            <el-option label="FileToDB" value="2"/>-->
<!--                            <el-option label="FileToFile" value="3"/>-->
                            <el-option v-for="item in syncTaskTypeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue"/>

                        </el-select>
                    </el-form-item>
                </el-col>
            </el-row>
            <CollapseHeader v-model="show1" tIndex="01" title="选择数据源" step1="源端"
                            step2="目的端"/>
            <ElCollapseTransition>
                <el-row v-show="show1" v-if="form.syncTaskType">
                    <el-col :span="12">
                        <component :is="getComponent" :form="form" :sourceList="sourceList"
                                   :dayWayList="dayWayList"></component>

                    </el-col>
                    <el-col :span="12">
                        <component :is="getComponent2" :form="form" :sourceList="sourceList"
                                   :dayWayList="dayWayList"></component>
                    </el-col>
                </el-row>
            </ElCollapseTransition>
            <CollapseHeader v-model="show2" v-if="form.syncTaskType && form.syncTaskType !== '3'" tIndex="02" title="字段映射"
                            step1="源端表字段"
                            step2="目标端表字段"/>
            <ElCollapseTransition>
                <div v-show="show2 && form.syncTaskType!=='3'" v-if=" form.syncTaskType && show2 ">
                    <div class="flex-center">
                        <el-button v-show="form.syncTaskType==='1'" type="primary" size="small" @click="handleSort('sameName')">同名映射</el-button>
                        <el-button v-show="form.syncTaskType==='1'" type="primary" size="small" @click="handleSort('sameRow')">同行映射</el-button>
                        <el-button v-show="form.syncTaskType==='1'" type="primary" size="small" @click="handleSort('reset')">重置</el-button>
                    </div>
                    <el-row style="height: 550px; margin: 10px 0">
                        <el-col :span="8" :offset="2">
                            <div v-show="form.syncTaskType==='1'" class="flex items-center">
                                <span>源端表字段</span>
                                <el-checkbox class="ml-10px"
                                             v-model="form.fCheckAll"
                                             @change="fHandleCheckAllChange"
                                >全选
                                </el-checkbox>
                            </div>
                            <el-scrollbar v-show="form.syncTaskType==='1'" height="500px" class="mt-5px">
                                <draggable
                                        class="draggable-main"
                                        item-key="left"
                                        :list="form.fColumnList || []"
                                        :group="{ name: 'drag',  pull: false,  put: false }"
                                        ghost-class="ghost"
                                        chosen-class="chosenClass"
                                        :scroll-speed="200"
                                >
                                    <template #item="{ element, index }">
                                        <div>
                                            <el-row>
                                                <el-col :span="2">
                                                    <div class="no">
                                                        <span>{{ index + 1 }}</span>
                                                    </div>
                                                </el-col>
                                                <el-col :span="22">
                                                    <div class="item">
                                                        <el-checkbox
                                                              v-model="element.isChecked" @change="onFieldChange">
                                                            {{ element.name }}
                                                        </el-checkbox>
                                                    </div>
                                                </el-col>
                                            </el-row>
                                        </div>
                                    </template>
                                </draggable>
                            </el-scrollbar>
                        </el-col>
                        <el-col v-show="form.syncTaskType!=='3'" :span="8" :offset="4">
                            <div class="flex items-center">
                                <span>目的端表字段</span>
                                <el-checkbox class="ml-10px"
                                             v-model="form.tCheckAll"
                                             @change="tHandleCheckAllChange"
                                >全选
                                </el-checkbox>
                            </div>
                            <el-scrollbar height="500px" class="mt-5px">
                                <draggable
                                        class="draggable-main"
                                        item-key="left"
                                        :list="form.tColumnList || []"
                                        :group="{  name: 'drag',  pull: false,put: false }"
                                        ghost-class="ghost"
                                        chosen-class="chosenClass"
                                        :scroll-speed="200"
                                >
                                    <template #item="{ element, index }">
                                        <div>
                                            <el-row>
                                                <el-col :span="2">
                                                    <div class="no">
                                                        <span>{{ index + 1 }}</span>
                                                    </div>
                                                </el-col>
                                                <el-col :span="22">
                                                    <div class="item">
                                                            <el-col :span="22">
                                                                <el-checkbox
                                                                    v-model="element.isChecked">
                                                                  {{ element.name }}
                                                                </el-checkbox>
                                                            </el-col>
                                                    </div>
                                                </el-col>
                                            </el-row>
                                        </div>
                                    </template>
                                </draggable>
                            </el-scrollbar>
                        </el-col>
                    </el-row>
                </div>
            </ElCollapseTransition>

          <CollapseHeader v-model="show3" :tIndex="`0${form.syncTaskType==='3' || !form.syncTaskType ? 2 : 3}`" title="脚本选择"/>
            <ElCollapseTransition>
                <el-row v-show="show3" v-if="form.syncTaskType">
                    <el-col :span="12">
                        <el-form-item label="脚本" prop="scriptName">
                            <div class="selector-container">
                                <el-input  v-model="form.scriptId" :value="scriptName" placeholder="请输入内容" style="flex: 1" clearable/>
                                <el-button  type="primary" style="margin-left: 12px" @click="selectScript">选择</el-button>
                                <Dialog
                                    width="70%"
                                    title="脚本选择"
                                    top="20%"
                                    :close-on-click-modal="false"
                                    :close-on-press-escape="false"
                                    v-model="scriptShow"
                                >
                                    <div class="view-container">
                                        <DataScript scriptStatus="1" @selectScriptData="selectScriptData" :isRadio="true"/>
                                    </div>
                                </Dialog>
                            </div>
                        </el-form-item>
                    </el-col>
                </el-row>
            </ElCollapseTransition>
            <CollapseHeader v-model="show4" :tIndex="`0${form.syncTaskType==='3' || !form.syncTaskType ? 3 : 4}`" title="控制规则"/>
            <ElCollapseTransition>
                <el-row v-show="show4" v-if="form.syncTaskType">
                    <el-col :span="12">
                        <el-form-item label="最大并发数" prop="maxThreads">
                            <el-input-number v-model="form.maxThreads" placeholder="请输入最大并发数" style="width:200px" clearable/>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="最大跳过错误行数" prop="maxIgnoreRows" label-width="140px">
                            <el-input-number v-model="form.maxIgnoreRows" placeholder="请输入最大跳过错误行数"
                                             style="width:250px" clearable/>
                        </el-form-item>
                    </el-col>
                </el-row>
            </ElCollapseTransition>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary" v-if="title!='查看'" @click="onConfirm()">确定</el-button>
                <el-button @click="show = false">关闭</el-button>
            </div>
        </template>
    </Dialog>



</template>

<script setup>
import {ref, computed, reactive, onMounted, unref, proxyRefs, watch} from 'vue';
import {Dialog} from '@/components/Dialog';
import {ElCollapseTransition, ElDialog, ElMessage} from 'element-plus';
import {intersectionWith, unionBy, differenceWith, isEqual} from 'lodash-es';
import Draggable from 'vuedraggable';
import CollapseHeader from './collapseHeader.vue';
import fromDb from './from/db.vue';
import fromFile from './from/file.vue';
import toDb from './to/db.vue';
import toFile from './to/file.vue';
import {cloneDeep} from 'lodash-es'
import {insert, updateById} from '@data/api/data/datacollection/api'
import DataScript from '@data/views/data/datascript/index.vue'


const props = defineProps({

    title: {
        type: String,
        default: ''
    },
    formData: {
        type: Object,
        default: () => {
        }
    },
    sourceList: {
        type: Array,
        default: () => []
    },
    dayWayList: {
        type: Array,
        default: () => []
    },
    syncTaskTypeList: {
        type: Array,
        default: () => []
    },
    scriptList: {
        type: Array,
        default: () => []
    },
});
const formRef = ref(null);
const scriptShow = ref(false);

const rules = {
    syncTaskName: [{required: true, message: '名称不能为空', trigger: 'blur'}],
    syncTaskType: [{required: true, message: '类型不能为空', trigger: 'change'}],
    //readerDatasourceId: [{required: true, message: '源端数据源不能为空', trigger: 'change'}],
    readerTables: [{required: true, message: '源端数据库不能为空', trigger: 'change'}],
    //writerDatasourceId: [{required: true, message: '目标数据源不能为空', trigger: 'change'}],
    writerTables: [{required: true, message: '目标数据库不能为空', trigger: 'change'}],
    querySql: [{required: true, message: '目标SQL语句不能为空', trigger: 'change'}],
    // syncMode: [{required: true, message: '同步方式不能为空', trigger: 'change'}],
    // syncField: [{required: true, message: '字段变量不能为空', trigger: 'change'}],
    // syncFieldType: [{required: true, message: '字段类型不能为空', trigger: 'change'}],
    // syncFieldDateformat: [{required: true, message: '字段格式不能为空', trigger: 'change'}],
    readerFileEncoding: [{required: true, message: '文件编码不能为空', trigger: 'change'}],
    writerFileEncoding: [{required: true, message: '文件编码不能为空', trigger: 'change'}],
    readerFilePath: [{required: true, message: '文件路径不能为空', trigger: 'change'}],
    //writerFilePath: [{required: true, message: '文件路径不能为空', trigger: 'change'}],
    readerFileDelimiter: [{required: true, message: '文件分隔符不能为空', trigger: 'change'}],
    writeMode: [{required: true, message: '写入前处理模式不能为空', trigger: 'change'}],
    fileFormat: [{required: true, message: '文件格式不能为空', trigger: 'change'}],
    maxThreads: [{required: true, message: '最大进程数不能为空', trigger: 'change'}],
    maxIgnoreRows: [{required: true, message: '最大跳过错误行数不能为空', trigger: 'change'}],
}


const emit = defineEmits(['confirm']);
const show = defineModel(); // 弹窗显示隐藏
const show1 = ref(true); // 01选择数据源折叠
const show2 = ref(true); // 02字段映射折叠
const show3 = ref(true); // 03脚本选择
const show4 = ref(true); // 04控制规则折叠


const form = proxyRefs(
    reactive({
      ...props.formData.data,
      syncTaskType: props.formData.data?.syncTaskType || '1', // 设置默认值
      fColumnList: props.formData.data?.fColumnList || [],
      tColumnList: props.formData.data?.tColumnList || [],
      fColumnListRaw: props.formData.data?.fColumnList
          ? props.formData.data.fColumnList.map(item => ({
            ...item,
            isChecked: false,
          })) : [],
      tColumnListRaw: props.formData.data?.tColumnList
          ? props.formData.data.tColumnList.map(item => ({
            ...item,
            isChecked: false,
          })) : [],
    })
);

show2.value = form.syncTaskType != '3';



const getComponent = computed(() => {
    return form.syncTaskType == '1' ? fromDb : fromFile
})

const getComponent2 = computed(() => {
    return form.syncTaskType == '3' ? toFile : toDb
})

const selectScript = () => {
    scriptShow.value = true;
}

const selectScriptData = (data) => {
    Object.keys(data).map(item => {
        form[item]  = data[item]
    })
    form.scriptId = form.id;
    form.scriptName = data.scriptName;
    scriptShow.value = false;
}


const onConfirm = () => {
    if (!formRef.value) {
        return
    }
    if(form.syncTaskType != '3') {
      let fColumnList = form.fColumnList.filter(item => item.isChecked);
      let tColumnList = form.tColumnList.filter(item => item.isChecked);

      if (form.syncTaskType == '1' && (fColumnList.length == 0 || tColumnList.length == 0)) {
        ElMessage.error("请选择字段变量");
        return;
      }


      if (form.syncTaskType == '2' && (tColumnList.length == 0)) {
        ElMessage.error("请选择字段变量");
        return;
      }


      if (form.syncTaskType == '1' && fColumnList.length != tColumnList.length) {
        ElMessage.error("同步字段列表长度不一致，请检查字段映射设置");
        return;
      }

      form.dataSyncColumnDTOList = [];
      tColumnList.forEach((item, index) => {
        const dataSyncColumnDTO = {
          targetColumnName: item.name,
        }
        if (fColumnList[index]) {
          dataSyncColumnDTO['srcColumnName'] = fColumnList[index].name
        }

        form.dataSyncColumnDTOList.push(dataSyncColumnDTO);
      })
    }

    if(form.skipHeaderBool != null){
      form.skipHeader = form.skipHeaderBool.toString();
      console.log("=toString",form.skipHeader);
    }

    if(form.supportFailOverBool != null){
      form.supportFailOver = form.supportFailOverBool.toString();
    }

    formRef.value.validate((valid) => {
        if (valid) {
            let obj = cloneDeep(form);
            delete obj.fColumnList;
            delete obj.tColumnList;
            delete obj.fColumnListRaw;
            delete obj.tColumnListRaw;

            let fun = props.formData.title.indexOf("修改") != -1 ? updateById : insert;
            fun(obj).then(res => {
                show.value = false
                // Message.success("操作成功");
                emit('confirm');
            }).catch(err => {
                ElMessage.error(err.message);
            })
        }
    })


};
const handleSort = (type) => {
    if (type === 'sameName') {
        form.fColumnList.forEach(item => item.isChecked = false);
        form.tColumnList.forEach(item => item.isChecked = false);
        const fColumnList = form.fColumnList || [];
        const tColumnList = form.tColumnList || [];
        const nameIndexMap = new Map();
        fColumnList.forEach((item, index) => {
            nameIndexMap.set(item.name, index);
        });

        const sortedFColumnList = fColumnList.filter(item => tColumnList.some(tItem => tItem.name === item.name))
            .concat(fColumnList.filter(item => !tColumnList.some(tItem => tItem.name === item.name)));

        form.fColumnList = sortedFColumnList;

        setTimeout(() => {
            const sortedTColumnList = new Array(fColumnList.length).fill(null);
            tColumnList.forEach(item => {
                const index = nameIndexMap.get(item.name);
                if (index !== undefined) {
                    sortedTColumnList[index] = item;
                }
            });
            const remainingItems = tColumnList.filter(item => !sortedTColumnList.includes(item));
            sortedTColumnList.push(...remainingItems);
            form.tColumnList = sortedTColumnList.filter(item => item !== null);

             let num  = 0;
            form.fColumnList.map((item,index) => {
                if (form.tColumnList[index] && form.tColumnList[index].name === item.name) {
                    num++;
                }
            })
            for (let i = 0; i < num; i++) {
                form.fColumnList[i].isChecked = true;
                form.tColumnList[i].isChecked = true;
            }
          updateSQL();
        }, 50);

    } else if (type === 'sameRow') {
        const length = Math.min(form.fColumnList?.length || 0, form.tColumnList?.length || 0);
        form.fColumnList.forEach(item => item.isChecked = false);
        form.tColumnList.forEach(item => item.isChecked = false);
        for (let i = 0; i < length; i++) {
            form.fColumnList[i].isChecked = true;
            form.tColumnList[i].isChecked = true;
        }
        updateSQL();
    } else if (type === 'reset') {
      if(form.fColumnListRaw) {
        form.fColumnList = cloneDeep(form.fColumnListRaw);
      } else {
        form.fColumnList = [];
      }
      if(form.tColumnListRaw) {
        form.tColumnList = cloneDeep(form.tColumnListRaw);
      } else {
        form.tColumnList = [];
      }
    }
};


const selectSyncTaskType = (val) => {
    console.log(show2.value)
    show2.value = val != '3';
    form.readerDatasourceId = '';
    form.readerTables = '';
    form.writerDatasourceId = '';
    form.writerTables = '';
    form.querySql = '';
    form.preSql = '';
    form.postSql = '';
    form.fColumnList = [];
    form.tColumnList = [];
    form.syncMode = '';
    form.specifyTime = [];
    form.specifyTimeStart = '';
    form.specifyTimeEnd = '';
    if(val !== "1"){
      rules.readerDatasourceId = [];
    } else {
      rules.readerDatasourceId = [{required: true, message: '源端数据源不能为空', trigger: 'change'}];

    }
    if(val === "3"){
      rules.writerDatasourceId = [];
    } else {
      rules.writerDatasourceId = [{required: true, message: '目标数据源不能为空', trigger: 'change'}];
    }
}

// 字段变化时更新 SQL
const onFieldChange = () => {
  updateSQL();  // 每当用户选择或取消选择字段时更新 SQL
  console.log(form.querySql)
};
// 更新 SQL 语句
const updateSQL = () => {
  if(form.fCheckAll){
    form.querySql = "select * " + form.querySql.substring(form.querySql.indexOf('from'));
    return;
  }
  // 获取选中的源端字段
  const selectedSourceFields = form.fColumnList
      .filter(item => item.isChecked)
      .map(item => item.name.toLowerCase());

  let sql = "select ";

  if (selectedSourceFields.length > 0) {
    sql += selectedSourceFields.join(', ');
  } else {
    sql += "*";  // 默认选择所有字段
  }

  sql += form.querySql.substring(form.querySql.indexOf(' from'));

  form.querySql = sql;
};

const fHandleCheckAllChange = (val) => {
    form.fColumnList.forEach(item => {
        item.isChecked = val;
    })
}

const tHandleCheckAllChange = (val) => {
    form.tColumnList.forEach(item => {
        item.isChecked = val;
    })
}

const scriptName = computed(() => {
  const script = props.scriptList.find(script => script.id === form.scriptId);
  return script ? script.scriptName : '';
});

const allFColumnChecked = computed(() => {
  return form.fColumnList.length>0 && form.fColumnList.every(item => item.isChecked);

});
const allTColumnChecked = computed(() => {
  return form.tColumnList.length>0 && form.tColumnList.every(item => item.isChecked);
});

// 监控字段的选择状态，自动更新全选框
watch(() => form.fColumnList, (newList) => {
  form.fCheckAll = allFColumnChecked.value;
  if(form.fCheckAll){
    form.querySql = "select * " + form.querySql.substring(form.querySql.indexOf('from'));
  }
}, { deep: true });
watch(() => form.tColumnList, (newList) => {
  form.tCheckAll = allTColumnChecked.value;
}, { deep: true });

onMounted( () => {
  form.fCheckAll = allFColumnChecked.value;
  form.tCheckAll = allTColumnChecked.value;
})

</script>

<style lang="scss" scoped>
.draggable-main {
  min-height: 28px;

  .item {
    border-radius: 2px;
    user-select: none;
    padding: 2px 10px;
    margin-bottom: 4px;
    box-sizing: border-box;
    background-color: #f0f2f5;

    &:hover {
      background-color: #dcdfe6;
      cursor: move;
    }
  }

  .no {
    margin-top: 6px;
    width: 20px;
    text-align: center;
  }
}

.ghost {
  background-color: #409eff !important;
  color: #fff;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}
.selector-container {
    width: 100%;
    display: flex;
    align-items: center;
}
</style>

